package nl.hanze.designpatterns.db;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;

public class RowIterator<T> implements Iterator<T> {
	private int colomCount = 0;
	private ResultSet rs;
	private ResultSetMetaData rsmeta;
	private Class<T> c;
	
	protected RowIterator(ResultSet rs, Class<T> c){
		this.rs = rs;
		this.c = c;
		
		try{
			rsmeta = rs.getMetaData();
			colomCount = rsmeta.getColumnCount();
	
		} catch (SQLException e){
			e.printStackTrace();
		}
	}
	
	@Override
	public boolean hasNext() {
		boolean isLastRow = false;
		try {
			isLastRow = rs.isLast();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		if (!isLastRow){
			return true;
		} else{
			return false;
		}
			
	}

	@Override
	public T next(){
		try{
			int index = 1;
			if (rs.next()){
				
				ArrayList<Class<?>> parameterList = new ArrayList <Class<?>>();
				ArrayList<Object> valueList = new ArrayList<Object>();
				while(index <= colomCount){
				Object parameterObject = rs.getObject(index);
				Class<?> parameterClass = parameterObject.getClass();
					
				Object parameterValue = rs.getObject(index);
				valueList.add(parameterValue);
				parameterList.add(parameterClass);
				index++;
				}
				
				//Maak array in juiste size
				Class<?>[] parameterArray = new Class<?>[parameterList.size()];
				Object[] initValues = new Object[valueList.size()];
				for (int i=0 ; i < parameterList.size() ; i++){
					parameterArray[i] = parameterList.get(i);
					initValues[i] = valueList.get(i);
				}
				Constructor<T> constructor = c.getConstructor(parameterArray);
				Object newInstance = constructor.newInstance(initValues);
				T resultObject = (T) newInstance;
				
				return resultObject;
				
			}
		
		} catch (SQLException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e){
				e.printStackTrace();
		}
		return null;
    }

	@Override
	public void remove() {
		throw new UnsupportedOperationException();
	}
}
